﻿using YNTK.Common.Core.Manager;
using YNTK.Common.Enum;
using YNTK.Common.Extension;
using YNTK.Common.Filter;
using YNTK.Dependency;
using YNTK.DynamicApiController;
using YNTK.FriendlyException;
using YNTK.WorkFlow.Entitys;
using YNTK.WorkFlow.Entitys.Enum;
using YNTK.WorkFlow.Interfaces.FlowEngine;
using YNTK.WorkFlow.Interfaces.FlowTask;
using YNTK.WorkFlow.Interfaces.FlowTask.Repository;
using YNTK.SubDev.Interfaces.ZyOaWfFinrmbt;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using SqlSugar.IOC;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using YNTK.SubDev.Entitys;
using YNTK.SubDev.Entitys.Dto.ZyOaWfFinrmbt;
using Yitter.IdGenerator;
using YNTK.Common.Helper;
using YNTK.JsonSerialization;
using YNTK.System.Interfaces.System;

namespace YNTK.SubDev.ZyOaWfFinrmbt
{
    /// <summary>
    /// 报销单服务
    /// </summary>
    [ApiDescriptionSettings(Tag = "SubDev",Name = "ZyOaWfFinrmbt", Order = 200)]
    [Route("api/SubDev/[controller]")]
    public class ZyOaWfFinrmbtService : IZyOaWfFinrmbtService, IDynamicApiController, ITransient
    {
        private readonly ISqlSugarRepository<ZyOaWfFinrmbtEntity> _zyOaWfFinrmbtRepository;
        private readonly ISqlSugarRepository<ZyOaWfFinrmbtDetailsEntity> _zyOaWfFinrmbtDetailsRepository;
        private readonly IBillRullService _billRuleService;
        private readonly SqlSugarScope _db;
        private readonly IUserManager _userManager;
        private readonly IFlowTaskService _flowTaskService;
        private readonly IFlowTaskRepository _flowTaskRepository;
        private readonly IFlowEngineService _flowEngineService;

        /// <summary>
        /// 初始化一个<see cref="ZyOaWfFinrmbtService"/>类型的新实例
        /// </summary>
        public ZyOaWfFinrmbtService(
            ISqlSugarRepository<ZyOaWfFinrmbtEntity> zyOaWfFinrmbtRepository,
            ISqlSugarRepository<ZyOaWfFinrmbtDetailsEntity> zyOaWfFinrmbtDetailsRepository,
            IBillRullService billRuleService,
            IUserManager userManager, 
            IFlowTaskService flowTaskService, 
            IFlowTaskRepository flowTaskRepository, 
            IFlowEngineService flowEngineService)
        {
            _zyOaWfFinrmbtRepository = zyOaWfFinrmbtRepository;            
            _db = _zyOaWfFinrmbtRepository.Context;
            _zyOaWfFinrmbtDetailsRepository = zyOaWfFinrmbtDetailsRepository;
            _billRuleService = billRuleService;
            _userManager = userManager;
            _flowTaskService = flowTaskService;
            _flowTaskRepository = flowTaskRepository;
            _flowEngineService = flowEngineService;
        }

        /// <summary>
        /// 获取报销单
        /// </summary>
        /// <param name="id">参数</param>
        /// <returns></returns>
        [HttpGet("{id}")]
        public async Task<dynamic> GetInfo(string id)
        {
            var entity = await _db.Queryable<ZyOaWfFinrmbtEntity>().FirstAsync(p => p.Id == id);
            var output = entity.Adapt<ZyOaWfFinrmbtInfoOutput>();
            
            var zyOaWfFinrmbtDetailsList = await _db.Queryable<ZyOaWfFinrmbtDetailsEntity>().Where(w => w.ReimbursementId == entity.Id).ToListAsync();
            output.zyOaWfFinrmbtDetailsList = zyOaWfFinrmbtDetailsList.Adapt<List<ZyOaWfFinrmbtDetailsInfoOutput>>();
            return output;
        }

        /// <summary>
		/// 获取报销单列表
		/// </summary>
		/// <param name="input">请求参数</param>
		/// <returns></returns>
        [HttpGet("")]
        public async Task<dynamic> GetList([FromQuery] ZyOaWfFinrmbtListQueryInput input)
        {
            var sidx = input.sidx == null ? "happedTime" : input.sidx;
            List<string> queryHappedTime = input.happedTime != null ? input.happedTime.Split(',').ToObeject<List<string>>() : null;
            DateTime? startHappedTime = queryHappedTime != null ? Ext.GetDateTime(queryHappedTime.First()) : null;
            DateTime? endHappedTime = queryHappedTime != null ? Ext.GetDateTime(queryHappedTime.Last()) : null;
            var data = await _db.Queryable<ZyOaWfFinrmbtEntity,FlowTaskEntity>((a,b) => new JoinQueryInfos(JoinType.Left, a.Id == b.Id))
                .WhereIF(!string.IsNullOrEmpty(input.proId), a => a.ProId.Equals(input.proId))
                .WhereIF(queryHappedTime != null, a => a.HappedTime >= new DateTime(startHappedTime.ToDate().Year, startHappedTime.ToDate().Month, startHappedTime.ToDate().Day, 0, 0, 0))
                .WhereIF(queryHappedTime != null, a => a.HappedTime <= new DateTime(endHappedTime.ToDate().Year, endHappedTime.ToDate().Month, endHappedTime.ToDate().Day, 23, 59, 59))
                .WhereIF(!string.IsNullOrEmpty(input.handler), a => a.Handler.Equals(input.handler))
                .Select((a,b)=> new 
                {
                    id = a.Id,
                    proId = a.ProId,
                    reimbursement = a.Reimbursement,
                    happedTime = a.HappedTime,
                    handler = a.Handler,
                    remark = a.Remark,
                    totalAmount = a.TotalAmount,
                    createTime = a.CreateTime,
                    categoryId = a.CategoryId,
                    flowState = b.Status,
                    flowId = b.FlowId
                }).MergeTable().Select<ZyOaWfFinrmbtListOutput>().OrderBy(sidx+" "+input.sort).ToPagedListAsync(input.currentPage, input.pageSize);
                return TkPageResult<ZyOaWfFinrmbtListOutput>.SqlSugarPageResult(data);
        }

        /// <summary>
        /// 新建报销单
        /// </summary>
        /// <param name="input">参数</param>
        /// <returns></returns>
        [HttpPost("")]
        public async Task Create([FromBody] ZyOaWfFinrmbtCrInput input)
        {
            var userInfo = await _userManager.GetUserInfo();
            var entity = input.Adapt<ZyOaWfFinrmbtEntity>();
            entity.Id = YitIdHelper.NextId().ToString();
            entity.Reimbursement = await _billRuleService.GetBillNumber("ZYBX_WF");
            entity.Handler = _userManager.UserId;
            entity.CreateTime = DateTime.Now;  
            try
            {
                //开启事务
                _db.Ado.BeginTran();
                
                //新增报销单记录
                var newEntity = await _db.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteReturnEntityAsync();

                var zyOaWfFinrmbtDetailsEntityList = input.zyOaWfFinrmbtDetailsList.Adapt<List<ZyOaWfFinrmbtDetailsEntity>>();
                foreach (var item in zyOaWfFinrmbtDetailsEntityList)
                {
                    item.Id = YitIdHelper.NextId().ToString();
                    item.ReimbursementId = newEntity.Id;
                }
                await _db.Insertable(zyOaWfFinrmbtDetailsEntityList).ExecuteCommandAsync();
                if (input.flowState == 0)
                {
                    var flowEngineEntity = await _flowEngineService.GetInfoByEnCode("#visualDevZyOaFinrmbt");
                    await FlowSubmit(newEntity.Id, flowEngineEntity);
                }
                //关闭事务
                _db.Ado.CommitTran();
            }
            catch (Exception)
            {
                //回滚事务
                _db.Ado.RollbackTran();
                throw YNTKException.Oh(ErrorCode.COM1000);
            }
        }

        /// <summary>
        /// 更新报销单
        /// </summary>
        /// <param name="id">主键</param>
        /// <param name="input">参数</param>
        /// <returns></returns>
        [HttpPut("{id}")]
        public async Task Update(string id, [FromBody] ZyOaWfFinrmbtUpInput input)
        {
            var entity = input.Adapt<ZyOaWfFinrmbtEntity>();
            entity.ModifyTime = DateTime.Now;  
            entity.ModifyPerson = _userManager.UserId;
            try
            {
                //开启事务
                _db.Ado.BeginTran();
                
                //更新报销单记录
                await _db.Updateable(entity).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();

                //清空原有数据
                await _db.Deleteable<ZyOaWfFinrmbtDetailsEntity>().Where(u => u.ReimbursementId == id).ExecuteCommandAsync();
                //新增新数据
                var zyOaWfFinrmbtDetailsEntityList = input.zyOaWfFinrmbtDetailsList.Adapt<List<ZyOaWfFinrmbtDetailsEntity>>();
                zyOaWfFinrmbtDetailsEntityList.ForEach(t =>
                {
                    t.Id = YitIdHelper.NextId().ToString();
                    t.ReimbursementId = entity.Id;
                });
                await _db.Insertable(zyOaWfFinrmbtDetailsEntityList).ExecuteCommandAsync();
                if (input.flowState.Equals(0))
                {
                    var flowEngineEntity = await _flowEngineService.GetInfoByEnCode("#visualDevZyOaFinrmbt");
                    await FlowSubmit(entity.Id, flowEngineEntity);
                }
                //关闭事务
                _db.Ado.CommitTran();
            }
            catch (Exception)
            {
                //回滚事务
                _db.Ado.RollbackTran();
                throw YNTKException.Oh(ErrorCode.COM1001);
            }
        }

        /// <summary>
        /// 删除报销单
        /// </summary>
        /// <returns></returns>
        [HttpDelete("{id}")]
        public async Task Delete(string id)
        {
            var entity = await _db.Queryable<ZyOaWfFinrmbtEntity>().FirstAsync(p => p.Id == id);
            _ = entity ?? throw YNTKException.Oh(ErrorCode.COM1005);
            try
            {
                //开启事务
                _db.Ado.BeginTran();
                
                //删除报销单记录
                await _db.Deleteable<ZyOaWfFinrmbtEntity>().Where(d => d.Id == id).ExecuteCommandAsync();

                //清空子表数据
                await _db.Deleteable<ZyOaWfFinrmbtDetailsEntity>().Where(u => u.ReimbursementId == id).ExecuteCommandAsync();
                
                //关闭事务
                _db.Ado.CommitTran();
            }
            catch (Exception)
            {
                //回滚事务
                _db.Ado.RollbackTran();
                throw YNTKException.Oh(ErrorCode.COM1002);
            }
        }
        /// <summary>
        /// 提交审核
        /// </summary>
        /// <param name="id">主键值</param>
        /// <param name="flowEngineEntity">流程信息</param>
        /// <returns></returns>
        private async Task FlowSubmit(string id, FlowEngineEntity flowEngineEntity)
        {
            var zyOaWfFinrmbtEntity = await _zyOaWfFinrmbtRepository.FirstOrDefaultAsync(x => x.Id == id);
            try
            {
                DbScoped.SugarScope.BeginTran();

                #region 业务信息
                
                zyOaWfFinrmbtEntity.ModifyTime = DateTime.Now;  
                zyOaWfFinrmbtEntity.ModifyPerson = _userManager.UserId;
                await _zyOaWfFinrmbtRepository.UpdateAsync(zyOaWfFinrmbtEntity);

                #endregion

                #region 流程信息
                var flowTaskEntity = await _flowTaskRepository.GetTaskInfo(id);
                if (flowTaskEntity.IsNullOrEmpty())
                {
                    await _flowTaskService.Submit("", flowEngineEntity.Id, id, _userManager.User.RealName + "的" + flowEngineEntity.FullName, 1, null, zyOaWfFinrmbtEntity.Adapt<ZyOaWfFinrmbtCrInput>(), 0);
                }
                else
                {
                    await _flowTaskService.Submit(id, flowEngineEntity.Id, id, _userManager.User.RealName + "的"  + flowEngineEntity.FullName, 1, null, zyOaWfFinrmbtEntity.Adapt<ZyOaWfFinrmbtCrInput>(), 0);
                }
                #endregion

                DbScoped.SugarScope.CommitTran();
            }
            catch (Exception)
            {
                DbScoped.Sugar.RollbackTran();
                throw;
            }
        }

        /// <summary>
        /// 撤回审核
        /// </summary>
        /// <param name="flowTaskEntity">流程任务</param>
        /// <param name="flowHandleModel">流程经办</param>
        private async Task FlowRevoke(FlowTaskEntity flowTaskEntity, string flowHandleModel)
        {
            var zyOaWfFinrmbtEntity = await _zyOaWfFinrmbtRepository.FirstOrDefaultAsync(x => x.Id == flowTaskEntity.ProcessId);
            try
            {
                DbScoped.SugarScope.BeginTran();

                #region 业务信息
                zyOaWfFinrmbtEntity.ModifyTime = DateTime.Now;  
                zyOaWfFinrmbtEntity.ModifyPerson = _userManager.UserId;
                await _zyOaWfFinrmbtRepository.UpdateAsync(zyOaWfFinrmbtEntity);
                #endregion

                #region 流程信息
                var flowTaskNodeEntityList = await _flowTaskRepository.GetTaskNodeList(flowTaskEntity.Id);
                var flowTaskNodeEntity = flowTaskNodeEntityList.Find(m => m.SortCode == 2);
                if (flowTaskNodeEntity.Completion > 0)
                {
                    throw new Exception("当前流程被处理，无法撤回流程");
                }
                else
                {
                    await _flowTaskService.Revoke(flowTaskEntity, flowHandleModel);
                }
                #endregion

                DbScoped.SugarScope.CommitTran();
            }
            catch (Exception)
            {
                DbScoped.Sugar.RollbackTran();
                throw;
            }
        }
    }
}